package cn.gg.benchmark.cases;

import cn.gg.benchmark.util.ArrayList;
import cn.gg.benchmark.util.StringUtil;

/**
 * <code>Suite</code>是测试项目的容器，其中包含若干个case或suite。<br>
 * <code>Suite</code>
 * 类实现了IBenchmarkable接口，对一个suite执行测试实际上循环执行其中的个IBenchmarkable对象的测试项目<br>
 * 采用Suite-Case模型的一个好处是，在外层调用时十分的方便，外层不必关心一个测试是一个测试项目还是一组测试项目，<br>
 * 只要利用代号通过工厂类就能得到一个IBenchmarkable对象，然后执行就可以了，这个思想十分类似JUnit中的组织方法。<br>
 * 
 * @see IBenchmarkable
 * @see NonGraphicsCase
 * @see CanvasGraphicsCase
 * @see GameCanvasGraphicsCase
 * 
 * @author Jarod Yv
 */
public class Suite implements IBenchmarkable, Runnable {
	/* Suite所包含的case的代码 */
	private ArrayList caseCodes;
	/* Suite的容器 */
	private Suite container;

	public void benchmark() {
		new Thread(this).start();
	}

	public void init() {

	}

	public void release() {
		// 清理caseCodes
		caseCodes.removeAll();
		caseCodes = null;
		// 如果Suite是另一个Suite的case，则唤醒其容器的线程
		if (container != null) {
			container.restartThread();
			container = null;
		}
	}

	public synchronized void run() {
		IBenchmarkable benchmark = null;
		// 循环执行Suite中的每一个Case
		for (int i = 0; i < caseCodes.size(); i++) {
			int code = StringUtil.Str2Int((String) caseCodes.get(i));// 获取case的代码
			if (code < 0)
				continue;// 如果case代码有问题的跳过，继续执行下一个case
			benchmark = CaseFactory.createCase(code);// 通过Case工厂获取case代码对应的case实例
			try {
				benchmark.init();// 初始化case
				benchmark.benchmark();// 执行测试内容
			} catch (Exception e) {
			} finally {
				benchmark = null;
				pauseThread();// 一旦case开始执行，则suite线程进入阻塞状态，知道case执行完毕后会将其再次激活
			}
		}
		release();// 所有case执行结束后，对Suite进行清理
	}

	/**
	 * 唤醒等待中的线程
	 */
	public synchronized void restartThread() {
		this.notify();
	}

	/**
	 * 中断运行中的线程
	 */
	public synchronized void pauseThread() {
		try {
			this.wait();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void setContainer(Suite container) {
		this.container = container;
	}
}
